#include <types.h>
#include <sys_config.h>
#include <retcode.h>
#include <api/libc/string.h>
#include <api/libc/printf.h>
#include <osal/osal.h>
#include <hld/hld_dev.h>
#include <hld/dis/vpo.h>
#include <hld/decv/vdec_driver.h>
#include <hld/decv/decv.h>

#include <api/libimagedec/imagedec.h>
#include <api/libmp/pe.h>
#include "../../image_engine.h"
#include "../../plugin.h"
#include <api/libfs2/stdio.h>

#define ENABLE_PE_CACHE
#ifdef 	ENABLE_PE_CACHE
#define	JPEG_BLOCK_SIZE		(320 * 1024)
#define JPEG_CACHE_SIZE		(JPEG_BLOCK_SIZE * 2)
static int jpg_cache_id = -1;
static UINT8 *jpg_cache_buffer;
#endif
//BOOL jpeg_decoder_task_not_over;        // added for bug fixing : avoid running of two decoder task at one time.
struct jpeg_file
{
	imagedec_id				id; 			//image id for decoder			
	Imagedec_Init_Config 	init_conf;		//configurefor decoder
	
	FILE					*fp;			//file pointer for JPEG
	unsigned long			task_terminated;	
	mp_callback_func		mp_cb;			//callback function for mp
	OSAL_ID					lock;
};

static struct jpeg_file jpeg_file;
static struct image_display_t dpy;

static int jpg_read_data(UINT32 fh,BYTE *buf, UINT32 size)
{
	int ret = 0;
#ifdef ENABLE_PE_CACHE
	if(jpg_cache_id >= 0)
	{
		ret = pe_cache_read(jpg_cache_id, buf, size, 0xFFFFFFFF);
		return ret;
	}
#endif	

#ifndef ENABLE_PE_CACHE
	FILE *fp =  (FILE*)fh;
	int byte_read;
	
	if(fp == NULL)
	{
		return -1;
	}

	byte_read = fread(buf, size, 1, fp);

	return ((byte_read < 0) ? 0 : byte_read) ;
#endif
	
}

static int jpg_seek_data(UINT32 fh,long offset, UINT32 origin)
{
#ifdef ENABLE_PE_CACHE
    if(jpg_cache_id >= 0)
    {
        pe_cache_seek(jpg_cache_id, (off_t)offset, origin);
        return 0;
    }
#endif

#ifndef ENABLE_PE_CACHE
	FILE *fp = (FILE*)fh;

	if(fp == NULL)
	{
		return -1;
	}

	fseek(fp, (off_t)offset, origin);
#endif
	return 0;
}

static UINT32 jpeg_process(void *value)
{
	unsigned long process = *(unsigned long*)value;
	unsigned long err = process >> 24;
	
	process = (process * 100) >> 16;

	if(process > 100) process = 100;
	
	osal_mutex_lock(jpeg_file.lock, TMO_FEVR);
	if(jpeg_file.mp_cb)
	{
		if(err == 0)
			jpeg_file.mp_cb(MP_IMAGE_DECODE_PROCESS, process);
		else
			jpeg_file.mp_cb(MP_IMAGE_DECODER_ERROR, err);
	}
	osal_mutex_unlock(jpeg_file.lock);

	return 0;
}

#if 0
enum Output_Frame_Ret_Code imagedec_mp_request(void *dev, void *pinfo);
BOOL imagedec_mp_release(void *dev,UINT8 utop_idx,UINT8 frm_array_idx);
enum Output_Frame_Ret_Code imagedec_mp_request_ext(void *dev,struct Display_Info *pinfo,struct Request_Info *pRequest_Info);
RET_CODE imagedec_mp_release_ext(void *pdev,struct Release_Info *pRelease_Info);//UINT8 utop_idx,UINT8 frm_array_idx)
#endif

static int jpeg_init(struct pe_image_cfg *pe_image_cfg)
{
	struct vpo_device * pvpo_sd;
	MEMSET(&jpeg_file, 0, sizeof(jpeg_file));

	jpeg_file.init_conf.frm_y_size	= pe_image_cfg->frm_y_size;
	jpeg_file.init_conf.frm_y_addr	= pe_image_cfg->frm_y_addr;
	jpeg_file.init_conf.frm_c_size	= pe_image_cfg->frm_c_size;
	jpeg_file.init_conf.frm_c_addr	= pe_image_cfg->frm_c_addr;
	jpeg_file.init_conf.frm2_y_size = pe_image_cfg->frm2_y_size;
	jpeg_file.init_conf.frm2_y_addr = pe_image_cfg->frm2_y_addr;
	jpeg_file.init_conf.frm2_c_size = pe_image_cfg->frm2_c_size;
	jpeg_file.init_conf.frm2_c_addr = pe_image_cfg->frm2_c_addr;
	jpeg_file.init_conf.decoder_buf = pe_image_cfg->decoder_buf;
	jpeg_file.init_conf.frm3_y_size = pe_image_cfg->frm3_y_size;
	jpeg_file.init_conf.frm3_y_addr = pe_image_cfg->frm3_y_addr;
	jpeg_file.init_conf.frm3_c_size = pe_image_cfg->frm3_c_size;
	jpeg_file.init_conf.frm3_c_addr = pe_image_cfg->frm3_c_addr;
	pvpo_sd = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1);
	if(NULL != pvpo_sd)
	{
		jpeg_file.init_conf.frm4_y_size	= pe_image_cfg->frm4_y_size;
		jpeg_file.init_conf.frm4_y_addr	= pe_image_cfg->frm4_y_addr;
		jpeg_file.init_conf.frm4_c_size	= pe_image_cfg->frm4_c_size;
		jpeg_file.init_conf.frm4_c_addr	= pe_image_cfg->frm4_c_addr;
	}
	jpeg_file.init_conf.decoder_buf_len = pe_image_cfg->decoder_buf_len;
	jpeg_file.init_conf.fread_callback = jpg_read_data;
	jpeg_file.init_conf.fseek_callback = jpg_seek_data;
	jpeg_file.init_conf.imagedec_status = jpeg_process;
    jpeg_file.init_conf.ALi2Dto3D_callback = pe_image_cfg->ALi_pic_2dto3d;

	if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F ||sys_ic_get_chip_id()==ALI_S3811)
		jpeg_file.init_conf.frm_mb_type = 1;
	else
		jpeg_file.init_conf.frm_mb_type = 0;

#ifdef ENABLE_PE_CACHE
	jpeg_file.init_conf.decoder_buf_len -= (JPEG_CACHE_SIZE + 0x200);
	jpg_cache_buffer = (unsigned char *)((((unsigned long)jpeg_file.init_conf.decoder_buf)+0xff) & 0xffffff00);
	jpg_cache_buffer = (unsigned char *)(((unsigned long)jpg_cache_buffer & 0x0fffffff) | 0x80000000);
	jpeg_file.init_conf.decoder_buf = (unsigned char *)(((unsigned long)jpeg_file.init_conf.decoder_buf + JPEG_CACHE_SIZE + 0x100 + 0x100)&0xffffff00);
#endif

	jpeg_file.id = imagedec_init(&jpeg_file.init_conf);
	jpeg_file.lock = osal_mutex_create();
	
}

static int jpeg_cleanup(void)
{
	if(jpeg_file.id > 0)
	{
		imagedec_release(jpeg_file.id);
		jpeg_file.id = 0;
		osal_mutex_delete(jpeg_file.lock);
	}
	
}
	
static int jpeg_is_our_file(char *filename)
{
	char *ext;
#ifndef	 _USE_32M_MEM_
	if( 3 == strlen(filename) && !strncasecmp(filename, "YUV", 3))
	{
		return TRUE;
	}
	
	ext = strrchr(filename, '.');
	if (ext)
	{
		if((!strncasecmp(ext, ".jpg", 4)) || (!strncasecmp(ext, ".jpeg", 5)) || (!strncasecmp(ext, ".bmp", 4)))
		{
			return TRUE;
		}
	}
#endif
	return FALSE;
}


void jpg_decoder_task(UINT32 para1,UINT32 para2)
{
	struct jpeg_file *pjpeg_file = (struct jpeg_file*)para1;
	struct image_display_t *dispy = (struct image_display_t*)para2;
	int ret;
	struct MPSource_CallBack imagedecMPCallBack;
	static struct PIPSource_CallBack PIPCallBack;
	static struct VDecPIPInfo tInitInfo;
	static struct vp_win_config_para win_para;
	struct vpo_device *pvpo_sd;
	Image_Display_Par dis_par;
	
	pvpo_sd = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1);
	pjpeg_file->task_terminated = 1;
//    jpeg_decoder_task_not_over = TRUE;      // initialized to TRUE, decoder task is not over
	//add for display 
	if(sys_ic_get_chip_id()==ALI_S3602F && -100==pjpeg_file->fp)
	{
		MEMSET(&dis_par, 0, sizeof(dis_par));
		
		dis_par.y = dispy->y_addr;
		
		dis_par.y_len = dispy->y_len;
		dis_par.c = dispy->c_addr;
		dis_par.c_len = dispy->c_len;
		dis_par.width = dispy->width;
		dis_par.height = dispy->height;
		dis_par.scantype = dispy->sample_format;

		ret = imagedec_display(pjpeg_file->id, &dis_par);
	}
	else
		{
#ifdef ENABLE_PE_CACHE
	pjpeg_file->fp = 1;			// avoid imagedec_decode return FALSE without FS API
#endif
	ret = imagedec_decode(pjpeg_file->id, (UINT32)pjpeg_file->fp);

#ifdef ENABLE_PE_CACHE
	pe_cache_close(jpg_cache_id);
	jpg_cache_id = -1;
#endif

#ifndef ENABLE_PE_CACHE
	fclose(pjpeg_file->fp);
#endif
		}
	pjpeg_file->fp = NULL;

    imagedec_de_config_videotoplay();
#if 0
    if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F ||sys_ic_get_chip_id()==ALI_S3811)
	{
		if(NULL != pvpo_sd && (sys_ic_get_chip_id()==ALI_S3602))
		{
			vdec_set_output((struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV),(enum VDecOutputMode)DUAL_MODE, &tInitInfo, &imagedecMPCallBack, &PIPCallBack);

	        win_para.source_number = 1;
			win_para.control_source_index = 0;
			win_para.source_info[0].attach_source_index = 1;
			win_para.source_info[0].src_callback.request_callback = (T_Request)(imagedecMPCallBack.RequestCallback);
			win_para.source_info[0].src_callback.release_callback = (T_Release)(imagedecMPCallBack.ReleaseCallback);
			win_para.source_info[0].src_callback.vblanking_callback= imagedecMPCallBack.vblanking_callback;
			win_para.source_info[0].src_module_devide_handle = dev_get_by_id(HLD_DEV_TYPE_DECV, 0);
			win_para.source_info[0].src_path_index = 1;
			win_para.window_number = 1;
			win_para.window_parameter[0].source_index = 0;
			win_para.window_parameter[0].display_layer = VPO_LAYER_MAIN;
	/*		win_para.window_parameter[0].rect.src_rect.uStartX = 0;
			win_para.window_parameter[0].rect.src_rect.uStartY = 0;
			win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
			win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
			win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
			win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
			win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
			win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;*/
			vpo_config_source_window( (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1), &win_para);
		}
		else
			vdec_set_output((struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV),(enum VDecOutputMode)MP_MODE, &tInitInfo, &imagedecMPCallBack, &PIPCallBack);
	}
	else
	{
		vdec_set_output((struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV), (enum VDecOutputMode) MP_MODE, &tInitInfo, &imagedecMPCallBack, &PIPCallBack);
	}
	vpo_win_mode((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_MAINWIN, &imagedecMPCallBack, NULL);
#endif
	pjpeg_file->task_terminated = 0;

	osal_mutex_lock(jpeg_file.lock, TMO_FEVR);
	if(pjpeg_file->mp_cb)
	{
		pjpeg_file->mp_cb(MP_IMAGE_PLAYBACK_END, 0);
	}
	osal_mutex_unlock(jpeg_file.lock);
//    jpeg_decoder_task_not_over = FALSE; // decoder task is over


/*		win_para.window_parameter[0].rect.src_rect.uStartX = 0;
		win_para.window_parameter[0].rect.src_rect.uStartY = 0;
		win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
		win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
		win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
		win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
		win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
		win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;*/
}

//struct Image_Display_Par *pimage_diplay = (struct Image_Display_Par *)para2; // add for image display from YUV


	
int jpeg_rotate(unsigned char rotate)
{
	int ret = -1;
#if 0
	struct MPSource_CallBack imagedecMPCallBack;
	struct vp_win_config_para win_para;
	struct vpo_device *gpvpo_sd;
	static struct PIPSource_CallBack PIPCallBack;
    static struct VDecPIPInfo tInitInfo;

	if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F || sys_ic_get_chip_id()==ALI_S3811)
	{
		imagedecMPCallBack.RequestCallback = (T_MPRequest)imagedec_mp_request_ext;
		imagedecMPCallBack.ReleaseCallback = (T_MPRelease)imagedec_mp_release_ext;
		imagedecMPCallBack.vblanking_callback = NULL;
		
		gpvpo_sd = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1);
		win_para.source_number = 1;
		win_para.control_source_index = 0;
		win_para.source_info[0].attach_source_index = 1;
		win_para.source_info[0].src_callback.request_callback = (T_Request)(imagedecMPCallBack.RequestCallback);
		win_para.source_info[0].src_callback.release_callback = (T_Release)(imagedecMPCallBack.ReleaseCallback);
		win_para.source_info[0].src_callback.vblanking_callback= NULL;;
		win_para.source_info[0].src_module_devide_handle = NULL;
		win_para.source_info[0].src_path_index = 1;
		win_para.window_number = 1;
		win_para.window_parameter[0].source_index = 0;
		win_para.window_parameter[0].display_layer = VPO_LAYER_MAIN;
/*		win_para.window_parameter[0].rect.src_rect.uStartX = 0;
		win_para.window_parameter[0].rect.src_rect.uStartY = 0;
		win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
		win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
		win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
		win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
		win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
		win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;*/
		if(NULL != gpvpo_sd)
			vpo_config_source_window(gpvpo_sd, &win_para);
	}
	else
	{
		imagedecMPCallBack.RequestCallback = (T_MPRequest)imagedec_mp_request;
		imagedecMPCallBack.ReleaseCallback = (T_MPRelease)imagedec_mp_release;
	}
    

	//call vpo io: config src_rect, dis_rect & request,release callback
	vpo_win_mode((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_MAINWIN, &imagedecMPCallBack, NULL);
#endif

    imagedec_de_config_imagetoplay();
	if(imagedec_rotate(jpeg_file.id, rotate, 0))
		ret = 1;

    imagedec_de_config_videotoplay();
#if 0
	if(sys_ic_get_chip_id()==ALI_S3602)
	{
		vdec_set_output((struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV),(enum VDecOutputMode)DUAL_MODE, &tInitInfo, &imagedecMPCallBack, &PIPCallBack);
		win_para.source_number = 1;
		win_para.control_source_index = 0;
		win_para.source_info[0].attach_source_index = 1;
		win_para.source_info[0].src_callback.request_callback = (T_Request)(imagedecMPCallBack.RequestCallback);
		win_para.source_info[0].src_callback.release_callback = (T_Release)(imagedecMPCallBack.ReleaseCallback);
		win_para.source_info[0].src_callback.vblanking_callback= imagedecMPCallBack.vblanking_callback;
		win_para.source_info[0].src_module_devide_handle = dev_get_by_id(HLD_DEV_TYPE_DECV, 0);
		win_para.source_info[0].src_path_index = 1;
		win_para.window_number = 1;
		win_para.window_parameter[0].source_index = 0;
		win_para.window_parameter[0].display_layer = VPO_LAYER_MAIN;
	/*	win_para.window_parameter[0].rect.src_rect.uStartX = 0;
		win_para.window_parameter[0].rect.src_rect.uStartY = 0;
		win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
		win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
		win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
		win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
		win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
		win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;*/
		gpvpo_sd = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1);
		if(NULL != gpvpo_sd)
			vpo_config_source_window(gpvpo_sd, &win_para);
	}
	vdec_set_output((struct vdec_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DECV),(enum VDecOutputMode)MP_MODE, &tInitInfo, &imagedecMPCallBack, &PIPCallBack);

    vpo_win_mode((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_MAINWIN, &imagedecMPCallBack, NULL);
#endif	
	return ret;
	
}
static int jpeg_decode(char *filename, void *args)
{
	OSAL_T_CTSK t_ctsk;
	OSAL_ID	tsk_id;

	struct image_config *cfg;
	struct image_display_t *display;
	Imagedec_Mode_Par Par, *pPar;
	struct vp_win_config_para win_para;
	struct vpo_device *gpvpo_sd;

	struct vpo_io_get_info dis_info;

	struct MPSource_CallBack imagedecMPCallBack;

	if(3 == strlen(filename) && !strcasecmp(filename, "YUV"))
	{
	//set the display parameter
		jpeg_file.fp = -100;
		display = (struct image_display_t *)args;
		MEMSET(&Par, 0, sizeof(Par));
		pPar = &Par;

		dpy.y_addr = display->y_addr;
		dpy.y_len = display->y_len;
		dpy.c_addr = display->c_addr;
		dpy.c_len = display->c_len;
		dpy.width = display->width;
		dpy.height =  display->height;
		dpy.sample_format = display->sample_format;

		if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F)
		{
			vpo_ioctl((struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 0), VPO_IO_GET_INFO, (UINT32) &dis_info);
		}

		jpeg_file.mp_cb = display->mp_cb;

		if(NULL ==  display)
		{
		//as full screen
			pPar->pro_show = 1;
			pPar->dis_rect.uStartX =  display->dest_left;
			pPar->dis_rect.uStartY =  display->dest_top;
			pPar->dis_rect.uWidth  =  display->dest_width;
			pPar->dis_rect.uHeight =  display->dest_height;

			pPar->src_rect.uStartX =  display->dest_left;
			pPar->src_rect.uStartY =  display->dest_top;
			pPar->src_rect.uWidth  =  display->dest_width;
			pPar->src_rect.uHeight =  display->dest_height;
		}
		else if( display->decode_mode == IMAGEDEC_REAL_SIZE)
		{
			pPar->pro_show = 1;
			pPar->dis_rect.uStartX = 0;
			pPar->dis_rect.uStartY = 0;

			if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F)
			{
				pPar->src_rect.uStartX = 0;
				pPar->src_rect.uStartY = 0;
				switch(dis_info.tvsys)
				{
					case LINE_720_25:
					case LINE_720_30:
						pPar->dis_rect.uWidth = 1280;
						pPar->dis_rect.uHeight = 720;
	
						pPar->src_rect.uWidth = 1280;
						pPar->src_rect.uHeight = 720;
						break;
					case LINE_1080_25:
					case LINE_1080_30:
                		case LINE_1080_50:
                		case LINE_1080_60:
                		case LINE_1080_24:
                		case LINE_1080_ASS:
                		case LINE_1152_ASS:    
						pPar->dis_rect.uWidth = 1920;
						pPar->dis_rect.uHeight = 1080;
	
						pPar->src_rect.uWidth = 1920;
						pPar->src_rect.uHeight = 1080;
						break;
					default:
						pPar->dis_rect.uWidth = 720;
						pPar->dis_rect.uHeight = 576;
	
						pPar->src_rect.uWidth = 720;
						pPar->src_rect.uHeight = 576;
					break;
				}
			}
			else
			{
				pPar->dis_rect.uWidth  = 720;
				pPar->dis_rect.uHeight = 576;

				pPar->src_rect.uStartX =  display->src_left;
				pPar->src_rect.uStartY =  display->src_top;
				pPar->src_rect.uWidth  =  display->src_width;
				pPar->src_rect.uHeight = display->src_height;
			}
		}
		else
		{
		//default as full screen
			pPar->pro_show = 1;
			if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F)
			{

				pPar->dis_rect.uStartX = 0;
				pPar->dis_rect.uStartY = 0;

				pPar->src_rect.uStartX = 0;
				pPar->src_rect.uStartY = 0;
				switch(dis_info.tvsys)
				{
					case LINE_720_25:
					case LINE_720_30:
						pPar->dis_rect.uWidth = 1280;
						pPar->dis_rect.uHeight = 720;

						pPar->src_rect.uWidth = 1280;
						pPar->src_rect.uHeight = 720;
					break;
				case LINE_1080_25:
				case LINE_1080_30:
                case LINE_1080_50:
                case LINE_1080_60:
                case LINE_1080_24:
                case LINE_1080_ASS:
                case LINE_1152_ASS:    
					pPar->dis_rect.uWidth = 1920;
					pPar->dis_rect.uHeight = 1080;

					pPar->dis_rect.uWidth = 1920;
					pPar->dis_rect.uHeight = 1080;
					break;
				default:
					pPar->dis_rect.uWidth = 720;
					pPar->dis_rect.uHeight = 576;

					pPar->src_rect.uWidth = 720;
					pPar->src_rect.uHeight = 576;
					break;
			}
		}
		else
		{
			pPar->dis_rect.uStartX =  display->dest_left;
			pPar->dis_rect.uStartY =  display->dest_top;
			pPar->dis_rect.uWidth  =  display->dest_width;
			pPar->dis_rect.uHeight =  display->dest_height;

			pPar->src_rect.uStartX =  display->dest_left;
			pPar->src_rect.uStartY =  display->dest_top;
			pPar->src_rect.uWidth  =  display->dest_width;
			pPar->src_rect.uHeight =  display->dest_height;
		}
		}

		if( display->effect == NULL)
		{
			pPar->show_mode = M_NORMAL;
		}
		else
		{
			pPar->show_mode =  display->effect->mode;
			pPar->show_mode_par = (UINT8 *)&display->effect->mode_param;
		}
		if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F)
		{
			imagedec_set_mode(jpeg_file.id,  display->decode_mode, pPar);
		}
		else
		{
			imagedec_rotate(jpeg_file.id,  display->rotate, 1);
			imagedec_set_mode(jpeg_file.id,  display->decode_mode, pPar);
		}
#if 0
		if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F)
		{
			imagedecMPCallBack.RequestCallback = (T_MPRequest)imagedec_mp_request_ext;
			imagedecMPCallBack.ReleaseCallback = (T_MPRelease)imagedec_mp_release_ext;
			imagedecMPCallBack.vblanking_callback = NULL;

			gpvpo_sd = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1);
			win_para.source_number = 1;
			win_para.control_source_index = 0;
			win_para.source_info[0].attach_source_index = 1;
			win_para.source_info[0].src_callback.request_callback = (T_Request)(imagedecMPCallBack.RequestCallback);
			win_para.source_info[0].src_callback.release_callback = (T_Release)(imagedecMPCallBack.ReleaseCallback);
			win_para.source_info[0].src_callback.vblanking_callback= NULL;;
			win_para.source_info[0].src_module_devide_handle = NULL;
			win_para.source_info[0].src_path_index = 1;
			win_para.window_number = 1;
			win_para.window_parameter[0].source_index = 0;
			win_para.window_parameter[0].display_layer = VPO_LAYER_MAIN;
/*		win_para.window_parameter[0].rect.src_rect.uStartX = 0;
		win_para.window_parameter[0].rect.src_rect.uStartY = 0;
		win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
		win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
		win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
		win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
		win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
		win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;*/
			if (NULL != gpvpo_sd)
				vpo_config_source_window(gpvpo_sd, &win_para);
		}
		else
		{
			imagedecMPCallBack.RequestCallback = (T_MPRequest)imagedec_mp_request;
			imagedecMPCallBack.ReleaseCallback = (T_MPRelease)imagedec_mp_release;
		}
    
		vpo_win_mode((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_MAINWIN, &imagedecMPCallBack, NULL);

#endif
    imagedec_de_config_imagetoplay();

		//create the decode task
		t_ctsk.itskpri = OSAL_PRI_NORMAL;
		t_ctsk.stksz = 0x6000;
		t_ctsk.quantum = 10;
		t_ctsk.para1 = (UINT32)&jpeg_file;
		t_ctsk.para2 = (UINT32)&dpy;
		t_ctsk.name[0] = 'J';
		t_ctsk.name[1] = 'P';
		t_ctsk.name[2] = 'G';
		t_ctsk.task = jpg_decoder_task;
		tsk_id = osal_task_create(&t_ctsk);
		if(OSAL_INVALID_ID == tsk_id)
		{
			return -1;
		}
	}
	else
	{
#ifndef ENABLE_PE_CACHE
	FILE *fp = fopen(filename, "rb");
	if(fp == NULL)
	{
		return -1;
	}
	jpeg_file.fp = fp;
#endif

	//set the decode parameter
	cfg = (struct image_config*)args;

	MEMSET(&Par, 0, sizeof(Par));
	pPar = &Par;

	if(!MEMCMP(filename, "http://", 7)) {
		pPar->file_type = TRUE;
	} else {
		pPar->file_type = FALSE;
	}

	if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F ||sys_ic_get_chip_id()==ALI_S3811)
	{
		vpo_ioctl((struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 0), VPO_IO_GET_INFO, (UINT32) &dis_info);
	}

	jpeg_file.mp_cb = cfg->mp_cb;
	if(cfg == NULL)
	{
		//as full screen
		pPar->pro_show = 1;
		pPar->dis_rect.uStartX = cfg->dest_left;
		pPar->dis_rect.uStartY = cfg->dest_top;
		pPar->dis_rect.uWidth  = cfg->dest_width;
		pPar->dis_rect.uHeight = cfg->dest_height;

		pPar->src_rect.uStartX = cfg->dest_left;
		pPar->src_rect.uStartY = cfg->dest_top;
		pPar->src_rect.uWidth  = cfg->dest_width;
		pPar->src_rect.uHeight = cfg->dest_height;
	}
	else if((cfg->decode_mode == IMAGEDEC_THUMBNAIL) || cfg->decode_mode == IMAGEDEC_MULTI_PIC)
	{
		pPar->pro_show = 1;
		pPar->dis_rect.uStartX = cfg->dest_left;
		pPar->dis_rect.uStartY = cfg->dest_top;
		pPar->dis_rect.uWidth  = cfg->dest_width + 4;
		pPar->dis_rect.uHeight = cfg->dest_height + 4;

		pPar->src_rect.uStartX = 0;
		pPar->src_rect.uStartY = 0;
		pPar->src_rect.uWidth  = 720;
		pPar->src_rect.uHeight = 576;
				
	}
	else if(cfg->decode_mode == IMAGEDEC_SIZEDEFINE)
	{
		pPar->pro_show = 1;
		pPar->dis_rect.uStartX = cfg->dest_left;
		pPar->dis_rect.uStartY = cfg->dest_top;
		pPar->dis_rect.uWidth  = cfg->dest_width;
		pPar->dis_rect.uHeight = cfg->dest_height;

		pPar->src_rect.uStartX = 0;
		pPar->src_rect.uStartY = 0;
		pPar->src_rect.uWidth  = 720;
		pPar->src_rect.uHeight = 576;
				
	}
	else if(cfg->decode_mode == IMAGEDEC_REAL_SIZE)
	{
		pPar->pro_show = 1;
		pPar->dis_rect.uStartX = 0;
		pPar->dis_rect.uStartY = 0;

		if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F || sys_ic_get_chip_id()==ALI_S3811)
		{
			pPar->src_rect.uStartX = 0;
			pPar->src_rect.uStartY = 0;
			switch(dis_info.tvsys)
			{
				case LINE_720_25:
				case LINE_720_30:
					pPar->dis_rect.uWidth = 1280;
					pPar->dis_rect.uHeight = 720;
	
					pPar->src_rect.uWidth = 1280;
					pPar->src_rect.uHeight = 720;
					break;
				case LINE_1080_25:
				case LINE_1080_30:
                case LINE_1080_50:
                case LINE_1080_60:
                case LINE_1080_24:
                case LINE_1080_ASS:
                case LINE_1152_ASS:    
					pPar->dis_rect.uWidth = 1920;
					pPar->dis_rect.uHeight = 1080;
	
					pPar->src_rect.uWidth = 1920;
					pPar->src_rect.uHeight = 1080;
					break;
				default:
					pPar->dis_rect.uWidth = 720;
					pPar->dis_rect.uHeight = 576;
	
					pPar->src_rect.uWidth = 720;
					pPar->src_rect.uHeight = 576;
					break;
			}
		}
		else
		{
			pPar->dis_rect.uWidth  = 720;
			pPar->dis_rect.uHeight = 576;

			pPar->src_rect.uStartX = cfg->src_left;
			pPar->src_rect.uStartY = cfg->src_top;
			pPar->src_rect.uWidth  = cfg->src_width;
			pPar->src_rect.uHeight = cfg->src_height;
		}
	}
	else
	{
		//default as full screen
		pPar->pro_show = 1;
		if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F || sys_ic_get_chip_id()==ALI_S3811)
		{

			pPar->dis_rect.uStartX = 0;
			pPar->dis_rect.uStartY = 0;

			pPar->src_rect.uStartX = 0;
			pPar->src_rect.uStartY = 0;
			switch(dis_info.tvsys)
			{
				case LINE_720_25:
				case LINE_720_30:
					pPar->dis_rect.uWidth = 1280;
					pPar->dis_rect.uHeight = 720;

					pPar->src_rect.uWidth = 1280;
					pPar->src_rect.uHeight = 720;
					break;
				case LINE_1080_25:
				case LINE_1080_30:
                case LINE_1080_50:
                case LINE_1080_60:
                case LINE_1080_24:
                case LINE_1080_ASS:
                case LINE_1152_ASS:    
					pPar->dis_rect.uWidth = 1920;
					pPar->dis_rect.uHeight = 1080;

					pPar->dis_rect.uWidth = 1920;
					pPar->dis_rect.uHeight = 1080;
					break;
				default:
					pPar->dis_rect.uWidth = 720;
					pPar->dis_rect.uHeight = 576;

					pPar->src_rect.uWidth = 720;
					pPar->src_rect.uHeight = 576;
					break;
			}
		}
		else
		{
			pPar->dis_rect.uStartX = cfg->dest_left;
			pPar->dis_rect.uStartY = cfg->dest_top;
			pPar->dis_rect.uWidth  = cfg->dest_width;
			pPar->dis_rect.uHeight = cfg->dest_height;

			pPar->src_rect.uStartX = cfg->dest_left;
			pPar->src_rect.uStartY = cfg->dest_top;
			pPar->src_rect.uWidth  = cfg->dest_width;
			pPar->src_rect.uHeight = cfg->dest_height;
		}
	}
		if(cfg->effect == NULL)
		{
			pPar->show_mode = M_NORMAL;
		}
		else
		{
			pPar->show_mode = cfg->effect->mode;
			pPar->show_mode_par = (UINT8 *)&cfg->effect->mode_param;
		}
	if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F || sys_ic_get_chip_id()==ALI_S3811)
		{
			imagedec_set_mode(jpeg_file.id, cfg->decode_mode, pPar);
		}
		else
		{
			imagedec_rotate(jpeg_file.id, cfg->rotate, 1);
			imagedec_set_mode(jpeg_file.id, cfg->decode_mode, pPar);
		}
#if 0		
	if(sys_ic_get_chip_id()==ALI_S3602 || sys_ic_get_chip_id()==ALI_S3602F || sys_ic_get_chip_id()==ALI_S3811)
	{
		imagedecMPCallBack.RequestCallback = (T_MPRequest)imagedec_mp_request_ext;
		imagedecMPCallBack.ReleaseCallback = (T_MPRelease)imagedec_mp_release_ext;
		imagedecMPCallBack.vblanking_callback = NULL;

		gpvpo_sd = (struct vpo_device *)dev_get_by_id(HLD_DEV_TYPE_DIS, 1);
		win_para.source_number = 1;
		win_para.control_source_index = 0;
		win_para.source_info[0].attach_source_index = 1;
		win_para.source_info[0].src_callback.request_callback = (T_Request)(imagedecMPCallBack.RequestCallback);
		win_para.source_info[0].src_callback.release_callback = (T_Release)(imagedecMPCallBack.ReleaseCallback);
		win_para.source_info[0].src_callback.vblanking_callback= NULL;;
		win_para.source_info[0].src_module_devide_handle = NULL;
		win_para.source_info[0].src_path_index = 1;
		win_para.window_number = 1;
		win_para.window_parameter[0].source_index = 0;
		win_para.window_parameter[0].display_layer = VPO_LAYER_MAIN;
/*		win_para.window_parameter[0].rect.src_rect.uStartX = 0;
		win_para.window_parameter[0].rect.src_rect.uStartY = 0;
		win_para.window_parameter[0].rect.src_rect.uWidth = PICTURE_WIDTH;
		win_para.window_parameter[0].rect.src_rect.uHeight = PICTURE_HEIGHT;	
		win_para.window_parameter[0].rect.dst_rect.uStartX = 0;
		win_para.window_parameter[0].rect.dst_rect.uStartY = 0;
		win_para.window_parameter[0].rect.dst_rect.uWidth = SCREEN_WIDTH;
		win_para.window_parameter[0].rect.dst_rect.uHeight = SCREEN_HEIGHT;*/
		if (NULL != gpvpo_sd)
			vpo_config_source_window(gpvpo_sd, &win_para);
	}
	else
	{
		imagedecMPCallBack.RequestCallback = (T_MPRequest)imagedec_mp_request;
		imagedecMPCallBack.ReleaseCallback = (T_MPRelease)imagedec_mp_release;
	}
    
	vpo_win_mode((struct vpo_device *)dev_get_by_type(NULL, HLD_DEV_TYPE_DIS), VPO_MAINWIN, &imagedecMPCallBack, NULL);
#endif   
    imagedec_de_config_imagetoplay();

#ifdef ENABLE_PE_CACHE
	jpg_cache_id = pe_cache_open(filename, jpg_cache_buffer, JPEG_CACHE_SIZE, JPEG_BLOCK_SIZE);
	if (jpg_cache_id < 0)
	{	
		pe_cache_close(jpg_cache_id);
		jpg_cache_id = -1;
		return -1;
	}
#endif

	osal_task_sleep(20);

#ifdef ENABLE_PE_CACHE
	jpeg_file.fp = 1;			// avoid imagedec_decode return FALSE without FS API
#endif
	if( !imagedec_check_fileheader(jpeg_file.id, jpeg_file.fp) )
	{
#ifdef ENABLE_PE_CACHE
	pe_cache_close(jpg_cache_id);
	jpg_cache_id = -1;
#endif

#ifndef ENABLE_PE_CACHE
	fclose(jpeg_file.fp);
#endif
	jpeg_file.fp = NULL;
		return -1;
	}
	//create the decode task
	t_ctsk.itskpri = OSAL_PRI_NORMAL;
	t_ctsk.stksz = 0x6000;
	t_ctsk.quantum = 10;
	t_ctsk.para1 = (UINT32)&jpeg_file;
	t_ctsk.para2 = (UINT32)NULL;
	t_ctsk.name[0] = 'J';
	t_ctsk.name[1] = 'P';
	t_ctsk.name[2] = 'G';
	t_ctsk.task = jpg_decoder_task;
	tsk_id = osal_task_create(&t_ctsk);
	if(OSAL_INVALID_ID == tsk_id)
	{
		return -1;
	}
		}
	return 0;
}

static int jpeg_show(void)
{
	imagedec_dis_next_pic(jpeg_file.id, 0, OSAL_WAIT_FOREVER_TIME);
}

static int jpeg_abort(void)
{
	if(jpeg_file.id > 0)
	{
		osal_mutex_lock(jpeg_file.lock, TMO_FEVR);
		jpeg_file.mp_cb = NULL;
		osal_mutex_unlock(jpeg_file.lock);

		imagedec_stop(jpeg_file.id);

		while(jpeg_file.task_terminated == 1)
		{
			osal_task_sleep(10);
		}
	}	 
}

static int jpeg_get_info(char *filename, struct image_info *info)
{
	Image_info ifo;
	BOOL ret;
	FILE *fp;

#ifndef ENABLE_PE_CACHE
	fp = fopen(filename, "rb");
	if(fp == NULL)
	{
		return -1;
	}

	fseek(fp, 0, SEEK_END);
	info->fsize = ftell(fp);
#else
	jpg_cache_id = pe_cache_open(filename, jpg_cache_buffer, JPEG_CACHE_SIZE, JPEG_BLOCK_SIZE);
	if(jpg_cache_id < 0)
	{	
		pe_cache_close(jpg_cache_id);
		jpg_cache_id = -1;
		return -1;
	}
	
	pe_cache_seek(jpg_cache_id, 0, SEEK_END);
	info->fsize = pe_cache_tell(jpg_cache_id);
#endif

	ret = imagedec_getinfo(jpeg_file.id, (UINT32)fp, &ifo);

#ifndef ENABLE_PE_CACHE
	fclose(fp);
#else
	pe_cache_close(jpg_cache_id);
	jpg_cache_id = -1;
#endif
	
	if(ret)
	{
		info->height = ifo.image_height;
		info->width  = ifo.image_width;
		info->bbp    = ifo.precision;
		return 0;
	}
	return -1;
	
}

static int jpeg_zoom(struct Rect *dstRect, struct Rect *srcRest)
{
	return imagedec_zoom(jpeg_file.id, *dstRect, *srcRest);
}


static int jpeg_swap(int type)
{
	return imagedec_swap(jpeg_file.id, type);
}

static int jpeg_option(int output_format, int user_depth, int user_shift, int user_vip)
{
	return imagedec_3D_user_option(jpeg_file.id, output_format, user_depth, user_shift, user_vip);
}

static int jpeg_set_disp_param(int display_type, int output_format, int user_depth, int user_shift, int user_vip)
{
    return imagedec_set_disp_param(jpeg_file.id, display_type, output_format, user_depth, user_shift, user_vip);
}


ImagePlugin jpeg_plugin =
{
	.handle = 0,
	.filename = NULL,
	.description = NULL,
	.init = jpeg_init,
	.about = NULL,
	.configure = NULL,
	.is_our_file = jpeg_is_our_file,
	.decode = jpeg_decode,
	.show = jpeg_show,
	.abort = jpeg_abort,
	.cleanup = jpeg_cleanup,
	.get_info = jpeg_get_info,
	.rotate = jpeg_rotate,
	.zoom = jpeg_zoom,
	.swap = jpeg_swap,
	.option = jpeg_option,
	.set_param = jpeg_set_disp_param,
};


